﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using Zcu.PanelComposer.Interfaces;
using Caliburn.Micro;
using Zcu.PanelComposer.Models.Model;
using Caliburn.Micro.Validation;
using System.ComponentModel.DataAnnotations;
using Zcu.PanelComposer.ViewModels.Events;

namespace Zcu.PanelComposer.ViewModels.Pages
{
    /// <summary>
    /// Zakladací/editacni stranka pro vazbu mezi projektem a solutionem.
    /// </summary>
    [Export(typeof(IModule))]
    public class NewSolutionProjectViewModel : ValidatingScreen<NewSolutionProjectViewModel>, IHandle<ActiveSolutionEvent>
    {
        #region Fields

        /// <summary>
        /// Reference na logger.
        /// </summary>
        private readonly ILog _log = LogManager.GetLog(typeof(NewSolutionProjectViewModel));

        private double? _XTranslate = 0f;
        private double? _YTranslate = 0f;
        private double? _ZTranslate = 0f;
        private double? _Angle = 0;

        private Project _SelectedProject;
        private BindableCollection<Project> _Project;
        private Solution _SelectedSolution;
        private SolutionProject _SelectedSolutionProject;

        #endregion

        #region Properties

        /// <summary>
        /// Gets the repository.
        /// </summary>
        [Import]
        public IRepository Repository { get; private set; }

        /// <summary>
        /// Gets a value indicating whether this instance is edit mode.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is edit mode; otherwise, <c>false</c>.
        /// </value>
        public bool IsEditMode { get; private set; }

        /// <summary>
        /// Gets or sets the selected solution project.
        /// </summary>
        /// <value>
        /// The selected solution project.
        /// </value>
        public SolutionProject SelectedSolutionProject
        {
            get { return _SelectedSolutionProject; }
            set
            {
                if (_SelectedSolutionProject != value) _SelectedSolutionProject = value;
                NotifyOfPropertyChange(() => SelectedSolutionProject);
            }
        }


        /// <summary>
        /// Gets or sets the selected solution.
        /// </summary>
        /// <value>
        /// The selected solution.
        /// </value>
        public Solution SelectedSolution
        {
            get { return _SelectedSolution; }
            set
            {
                if (_SelectedSolution != value) _SelectedSolution = value;
                NotifyOfPropertyChange(() => SelectedSolution);
            }
        }


        /// <summary>
        /// Gets or sets the selected project.
        /// </summary>
        /// <value>
        /// The selected project.
        /// </value>
        [Required]
        public Project SelectedProject
        {
            get { return _SelectedProject; }
            set
            {
                if (_SelectedProject != value) _SelectedProject = value;
                NotifyOfPropertyChange(() => SelectedProject);
                NotifyOfPropertyChange(() => CanSaveAction);
            }
        }

        /// <summary>
        /// Gets or sets the project.
        /// </summary>
        /// <value>
        /// The project.
        /// </value>
        public BindableCollection<Project> Project
        {
            get { return _Project; }
            set
            {
                if (_Project != value) _Project = value;
                NotifyOfPropertyChange(() => Project);
            }
        }

        /// <summary>
        /// Gets or sets the X translate.
        /// </summary>
        /// <value>
        /// The X translate.
        /// </value>
        [Required]
        public double? XTranslate
        {
            get { return _XTranslate; }
            set
            {
                if (_XTranslate != value) _XTranslate = value;
                NotifyOfPropertyChange(() => XTranslate);
            }
        }

        /// <summary>
        /// Gets or sets the Y translate.
        /// </summary>
        /// <value>
        /// The Y translate.
        /// </value>
        [Required]
        public double? YTranslate
        {
            get { return _YTranslate; }
            set
            {
                if (_YTranslate != value) _YTranslate = value;
                NotifyOfPropertyChange(() => YTranslate);
            }
        }

        /// <summary>
        /// Gets or sets the Z translate.
        /// </summary>
        /// <value>
        /// The Z translate.
        /// </value>
        [Required]
        public double? ZTranslate
        {
            get { return _ZTranslate; }
            set
            {
                if (_ZTranslate != value) _ZTranslate = value;
                NotifyOfPropertyChange(() => ZTranslate);
            }
        }

        /// <summary>
        /// Gets or sets the angle.
        /// </summary>
        /// <value>
        /// The angle.
        /// </value>
        [Required]
        public double? Angle
        {
            get { return _Angle; }
            set
            {
                if (_Angle != value) _Angle = value;
                NotifyOfPropertyChange(() => Angle);
            }
        }


        #endregion

        #region Guard properties

        /// <summary>
        /// Guard vlastnost nad tlacitkem Save.
        /// </summary>
        public bool CanSaveAction { get { return !HasErrors; } }

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="NewSolutionProjectViewModel"/> class.
        /// </summary>
        public NewSolutionProjectViewModel()
        {
            /// todo do resources
            DisplayName = "New solution's project";
            ModuleName = PageNames.NewSolutionProject;
            MenuVisible = false;
            Order = 99;
        }

        #endregion

        #region Overrided methods

        /// <summary>
        /// Udalost, ktera je volana hned po vytvoreni screenu.
        /// </summary>
        public override void OnReconstruct()
        {
            base.OnReconstruct();

            // registrace zachycovani udalosti zmeny projektu.
            EventAggregator.Subscribe(this);
        }

        /// <summary>
        /// Called when activating.
        /// </summary>
        protected override void OnActivate()
        {
            base.OnActivate();


            // zjisteni jestli jde o editaci ci novy projekt
            if (IsEditMode = Context != null && Context is SolutionProject)
            {
                _SelectedSolutionProject = (SolutionProject)Context;
            }
            else
            {
                _SelectedSolutionProject = new SolutionProject();
            }

            // nacteni dat z instance projektu
            LoadData();
        }

        protected override void OnColumnrror(string columnName, Dictionary<Type, string> errors)
        {
            base.OnColumnrror(columnName, errors);

            NotifyOfPropertyChange(() => CanSaveAction);
        }

        #endregion

        #region Public methods

        /// <summary>
        /// Akce, vyvolana stiskem tlacitka "Save".
        /// Ulozeni dat.
        /// </summary>
        public void SaveAction()
        {
            try
            {
                SelectedSolutionProject.Solution = SelectedSolution;
                SelectedSolutionProject.Project = SelectedProject;
                SelectedSolutionProject.X_Translate = XTranslate.Value;
                SelectedSolutionProject.Y_Translate = YTranslate.Value;
                SelectedSolutionProject.Z_Translate = ZTranslate.Value;
                SelectedSolutionProject.Angle_Rotation = Angle.Value;

                if (IsEditMode)
                {
                    SelectedSolution.UpdatedDate = DateTime.Now;
                }
                else
                {
                    Repository.Add<SolutionProject>(SelectedSolutionProject);
                }

                // commit do DB
                Repository.Commit();

                // presmerovani na detail solutionu
                Navigate(this.SourcePage);
            }
            catch (Exception ex)
            {
                _log.Error(ex);
                Repository.RollBackAll();
            }
        }

        /// <summary>
        /// Akce, vyvolana stiskem tlacitka "Back action".
        /// </summary>
        public void BackAction()
        {
            Navigate(this.SourcePage);
        }

        #endregion

        #region Handle events

        /// <summary>
        /// Zachyceni udalosti "aktivace solutionu".
        /// </summary>
        /// <param name="message">The message.</param>
        public void Handle(ActiveSolutionEvent message)
        {
            SelectedSolution = (Solution)message.Solution;
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Loads the data.
        /// </summary>
        private void LoadData()
        {
            Project = new BindableCollection<Models.Model.Project>(Repository.GetAll<Project>());

            SelectedProject = SelectedSolutionProject.Project;
            XTranslate = SelectedSolutionProject.X_Translate;
            YTranslate = SelectedSolutionProject.Y_Translate;
            ZTranslate = SelectedSolutionProject.Z_Translate;
            Angle = SelectedSolutionProject.Angle_Rotation;
        }

        #endregion}
    }
}
